import 'dart:async';

import 'package:moment_dart/moment_dart.dart';
import 'package:spendbook/common/http.dart';
import 'package:spendbook/models/user.dart';

class Util {
  formatDouble(dynamic value, {double def = 0.00}) {
    if (value is String) {
      return value.isEmpty ? def : double.parse(value);
    } else if (value is double) {
      return value.isNaN ? def : value;
    } else if (value is int) {
      return value.isNaN ? def : double.parse(value.toString());
    }
  }
}

class Model<T> extends Http with Util {
  int? id;

  String url = '';

  Moment? createdAt;

  Moment? updatedAt;

  User? user;

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> json = {'id': id};
    if (createdAt != null) {
      json['created_at'] = createdAt?.format('YYYY-MM-DD HH:mm:ss');
    }
    if (updatedAt != null) {
      json['updated_at'] = updatedAt?.format('YYYY-MM-DD HH:mm:ss');
    }
    if (user != null) {
      json['user'] = user!.toJson();
    }
    return json;
  }

  void fromJson(Map<String, dynamic> json) {
    id = int.parse(json['id'].toString());
    if (json.containsKey('user')) {
      user = User()..fromJson(json['user']);
    }
    if (json.containsKey('created_at')) {
      createdAt = Moment.parse(json['created_at']);
    }
    if (json.containsKey('updated_at')) {
      updatedAt = Moment.parse(json['updated_at']);
    }
  }

  bool checkStore() => true;

  bool checkFetch() => true;

  void afterStore() => {};

  void afterFetch() => {};

  Future<void> store() async {
    if (checkStore() == false) {
      return;
    }
    if (id != null) {
      await httpPut(url + '/' + id.toString(), toJson());
    } else {
      fromJson(await httpPost(url, toJson()));
    }
    afterStore();
  }

  FutureOr<void> fetchOne() async {
    if (checkFetch() == false) {
      return;
    }
    fromJson(await httpGet(url + '/' + id.toString()));
    afterFetch();
  }

  Future<List> fetch([Map<String, String>? params]) async {
    String query = '?';
    if (params != null) {
      params.forEach((key, value) {
        if (value != null) {
          query += '${key.toString()}=${value.toString()}&';
        }
      });
    }
    query = query.substring(0, query.length - 1);
    return await httpGet(url + query);
  }

  Future<void> delete() async {
    await httpDelete(url + '/' + id.toString());
  }
}
